<?php
/**
 * Control
 * @link https://code.google.com/p/yutori-php-framework/wiki/ModuleControll
 * 
 */
class Control {
	private $_request = null;

	public function __construct () {
		Y()->add(Y::func($this, 'loadModule'), 'Module');
		Y('Module')->add($this, __CLASS__);
		$thisY = Y()->add($this, 'Control');
		
		$method = $thisY->add('', 'Method');
		$method->add(Y::func($this, 'PathInfo'));

		$thisY->add(Y::func($this, 'resetRequest'), 'Reset');
		
		$thisY->add(DIR_APP.'/route', 'AppDir');
		$thisY->add(Y::file(DIR_APP."/app.php"), 'App');

		$request = $thisY->add(Y::func($this, 'PathInfo'), 'Request');

		Y()->add($_ENV, 'Env');

		Y()->add(array(), 'Config');
		Y()->add(array(), 'Model');
		Y()->add(array(), 'View');
	}

	public function call ($mode = 'WEB') {
		$thisY = Y('this');
		$thisY->add($mode, 'Mode');

		if ($mode == 'WEB') {
			if (0 === strcasecmp($_SERVER['HTTP_USER_AGENT'], 'Apache (internal dummy connection)')) exit();
			Y()->add($_SERVER, 'Server');
			Y()->add($_POST, 'Post');
			Y()->add($_GET, 'Get');
		}

		$thisY->child('App')->call();
		
		$request = $thisY->child('Request');
		$this->resetRequest();
		$dirApp = $thisY->child('AppDir')->call();
		$isExist = false;
		while (($curRequest = $request->call()) !== false) {
			$fullFile = $dirApp.DIRECTORY_SEPARATOR.$curRequest;
			if (is_dir ($fullFile)) {
				$dirApp = $fullFile;
				continue;
			} elseif (is_file ($fullFile)) {
				$isExist = true;
				include ($fullFile);
				break;
			} elseif (is_file ($dirApp.DIRECTORY_SEPARATOR.'notfound.php')) {
				$isExist = true;
				include ($dirApp.DIRECTORY_SEPARATOR.'notfound.php');
				break;
			}
		}
 		if ($isExist === false && is_file ($dirApp.DIRECTORY_SEPARATOR.'index.php')) {
				include ($dirApp.DIRECTORY_SEPARATOR.'index.php');
 		}
 		
 		Y('View')->call();
	}

	/**
	 * PathInfo
	 * @link https://code.google.com/p/yutori-php-framework/wiki/ModuleControll#Control.PathInfo
	 */
	public function PathInfo () {
		if (Y('Server')->isEmpty ()) return false;
		if ($this->_request === null) $this->_request = explode('/',trim(Y('Server.Path_Info')->call(),'/'));
		if (count($this->_request) > 0) return array_shift ($this->_request);
		else return false;
	}

	/**
	 * reset
	 * @link https://code.google.com/p/yutori-php-framework/wiki/ModuleControll#Control.Reset
	 */
	public function resetRequest () {
		$this->_request = null;
	}

	/**
	 * Module
	 * @link https://code.google.com/p/yutori-php-framework/wiki/ModuleControll#Module
	 */
	public function loadModule ($Module) {
		Y('Log.d')->call('モジュール読み込み開始:'.$Module);
		// ファイル名はすべて小文字。できれば大文字小文字の制限はなしにしたい。
		$Module = strtolower ($Module);
		// モジュールがロード済みなら何もしない
		if (!Y('Module.'.$Module)->isEmpty()) return true;
		// モジュールディレクトリを検索
		foreach (scandir (DIR_MODULES) as $dir) {
			if ($dir == '.' || $dir == '..') continue;
			$fulldir = DIR_MODULES.'/'.$dir;
			if (is_dir($fulldir)) {
				foreach (scandir ($fulldir) as $file) {
					if ($file == '.' || $file == '..') continue;
					if (is_file($fulldir.'/'.$file) && strcasecmp ($file, $Module.'.php') === 0) {
						include $fulldir.'/'.$file;
						return true;
					}
				}
			} elseif (is_file ($dir) && strcasecmp ($dir, $Module.'.php') === 0) {
				include $dir;
				return true;
			}
		}
		Y('Log.d')->call('モジュールの読み込みに失敗');
		return false;
	}


	/**
	 * リクエストを末尾に追加する。
	 * 
	 * @since 2012/01/20
	 * @param mixed $Request 追加するリクエストの値。配列にするとまとめて複数が追加される。
	 * @return void
	 */
	public function addRequest ($Request) {
		if (is_array($Request)) {
			// 配列リクエストは連想配列を受け付けないのでキーを数値化。
			$Request = array_values ($Request);
			$this->_request = array_merge ($this->_request, $Request);
		} else {
			$this->_request[] = $Request;
		}
		return;
	}

	/**
	 * リクエストを先頭に追加する。
	 * 
	 * @since 2012/01/20
	 * @param mixed $Request 追加するリクエストの値。配列にするとまとめて複数が追加される。
	 * @return void
	 */
	public function addRequestFirst ($Request) {
		if (is_array($Request)) {
			// 配列リクエストは連想配列を受け付けないのでキーを数値化。
			$Request = array_values ($Request);
			$this->_request = array_merge ($Request, $this->_request);
		} else {
			array_unshift($this->_request, $Request);
		}
		return;
	}

	/**
	 * リクエストを全て取得する。
	 * こちらの場合取得後の残りリクエストに変化はない。
	 * 
	 * @since 2012/01/20
	 * @return array 全リクエスト
	 */
	public function allRequest () {
		return $this->_request;
	}
}

new Control ();
